﻿using RQX.Common.Core.Extension;
using RQX.Common.Core.Logger;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace RQX.Common.Core.Hardware.BaseCollection
{
    public abstract class AbstractBaseCollection<T> : IIocCollection, IDisposable
    {
        #region Init
        /// <summary>
        /// 协议类型
        /// </summary>
        public abstract ProType ProType { get; }
        public abstract DeviceType DeviceType { get; }
        /// <summary>
        /// 是否记录接收日志
        /// </summary>
        public bool WriteRecvLog = true;
        /// <summary>
        /// 是否记录发送日志
        /// </summary>
        public bool WriteSendLog = true;
        /// <summary>
        /// 是否记录解析结果日志
        /// </summary>
        public bool WriteAnalysisLog = true;
        /// <summary>
        /// 是否记录调试日志
        /// </summary>
        public bool WriteDebugLog = true;
        /// <summary>
        /// 连接协议
        /// </summary>
        protected T _conn;
        /// <summary>
        /// 本机IP
        /// </summary>
        protected readonly string _localIP;
        protected readonly int _maxRecvTime = 2 * 60 * 1000;
        protected DateTime _lastRecvTime = DateTime.Now;
        private Timer _reStart_timer;//重启定时器
        protected readonly StringBuilder sb = new StringBuilder();
        protected AbstractBaseCollection() { }
        protected AbstractBaseCollection(StructureModel<T> structureModel)
        {
            _conn = structureModel.Conn;
            _localIP = structureModel.LocalIP ?? "127.0.0.1";
            _maxRecvTime = structureModel.MaxRecvTime > 0 ? structureModel.MaxRecvTime : _maxRecvTime;
        }
        #endregion

        #region 对外接口
        /// <summary>
        /// 开始
        /// </summary>
        public virtual void Start(bool isUseReStart = true)
        {
            //if (_conn.IsNull()) return;
            _lastRecvTime = DateTime.Now;
            if (isUseReStart) _reStart_timer = new Timer(new TimerCallback(ReStartMonitor), null, 1000, 1000);
            Connect(StepType.Init, null);
        }
        /// <summary>
        /// 解析后的数据处理事件
        /// </summary>
        public Action<Dictionary<string, string>> DealDataHandler { get; set; }
        /// <summary>
        /// 显示信息事件
        /// </summary>
        public Action<string> ShowMsgHandler { get; set; }
        /// <summary>
        /// 关闭
        /// </summary>
        public virtual void Dispose()
        {
            _reStart_timer?.Dispose();
        }
        /// <summary>
        /// 重启
        /// </summary>
        public virtual void ReStart()
        {
            LogUtils.WriteLogToConsole("重启了");
            T new_conn = _conn.IsNull() ? default : (T)Activator.CreateInstance(typeof(T), _conn);
            Dispose();
            Thread.Sleep(1000);
            _conn = new_conn;
            Start();
        }
        #endregion

        #region 虚函数
        /// <summary>
        /// 连接建立
        /// </summary>
        /// <param name="stepNum">步骤编号</param>
        protected abstract void Connect(StepType stepNum, string msg);
        /// <summary>
        /// 循环发送采集请求
        /// </summary>
        protected abstract void CircleSend();
        /// <summary>
        /// 将受到的数据通过结束符，切割为单条信息
        /// </summary>
        /// <returns></returns>
        protected abstract string CutToOneMsg(StringBuilder sb);
        /// <summary>
        /// 判断受到的数据类型,0为采集数据，1为连接建立完毕，可以开始循环采集，其他值为连接建立步骤
        /// </summary>
        /// <param name="buffer"></param>
        /// <returns></returns>
        protected abstract StepType CheckRecvMsgType(string lineStr);
        /// <summary>
        /// 具体解析数据
        /// </summary>
        /// <param name="buffer"></param>
        /// <returns></returns>
        protected abstract Dictionary<string, string> AnalysisData(string msg);
        #endregion

        #region 私有函数
        /// <summary>
        /// 记录接收数据日志
        /// </summary>
        /// <param name="msg"></param>
        protected virtual void WriteRecvLogMethod(string msg)
        {
            if (WriteRecvLog)
            {
                msg = $"recv ：{msg}";
                LogUtils.WriteLogToConsole(msg);
                LogUtils.WriteDebugLog(msg, _localIP);
            }
            ShowMsgHandler?.Invoke(msg);
        }
        /// <summary>
        /// 记录发送数据日志
        /// </summary>
        /// <param name="msg"></param>
        protected virtual void WriteSendLogMethod(string msg)
        {
            if (WriteSendLog)
            {
                msg = $"send ：{msg}";
                LogUtils.WriteLogToConsole(msg);
                LogUtils.WriteDebugLog(msg, _localIP);
            }
            ShowMsgHandler?.Invoke(msg);
        }
        /// <summary>
        /// 记录调试日志
        /// </summary>
        /// <param name="msg"></param>
        protected virtual void WriteDebugLogMethod(string msg)
        {
            if (WriteDebugLog)
            {
                LogUtils.WriteLogToConsole(msg);
                LogUtils.WriteDebugLog(msg, _localIP);
            }
            ShowMsgHandler?.Invoke(msg);
        }
        /// <summary>
        /// 记录解析结果数据日志
        /// </summary>
        /// <param name="msg"></param>
        protected virtual void WriteAnalysisLogMethod(IEnumerable<KeyValuePair<string, string>> dic)
        {
            dic.ForEach(item =>
            {
                var msg = $"analysis ：{item.Key} = {item.Value}";
                if (WriteAnalysisLog)
                {
                    LogUtils.WriteLogToConsole(msg);
                    LogUtils.WriteDebugLog(msg, _localIP);
                }
                ShowMsgHandler?.Invoke(msg);
            });
        }
        /// <summary>
        /// 接收到的buffer转为string，用于追加到StringBuilder中
        /// </summary>
        /// <param name="buffer"></param>
        /// <returns></returns>
        protected virtual string BufferTransferToString(byte[] buffer) => buffer.ToHex();
        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="buffer"></param>
        protected abstract void Send(byte[] buffer);
        /// <summary>
        /// 接收数据
        /// </summary>
        /// <param name="buffer"></param>
        protected virtual void RecvData(byte[] buffer)
        {
            _lastRecvTime = DateTime.Now;
            var recvStr = BufferTransferToString(buffer);
            WriteRecvLogMethod(recvStr);
            sb.Append(recvStr);
            var msg = CutToOneMsg(sb);
            try
            {
                sb.Remove(0, msg.Length);
            }
            catch (Exception ex)
            {
                LogUtils.WriteErrorLog($"{ex}", "127.0.0.1");
                sb.Clear();
            }
            var type = CheckRecvMsgType(msg);
            switch (type)
            {
                case StepType.DataSource://0为采集数据
                    var data = AnalysisData(msg);
                    WriteAnalysisLogMethod(data);
                    DealDataHandler?.Invoke(data);
                    break;
                case StepType.FinishConnect://1为连接建立完毕
                    Task.Run(() => CircleSend());
                    break;
                case StepType.None://不做任何操作
                    break;
                default:
                    Connect(type, msg);
                    break;
            }
        }
        /// <summary>
        /// 重启监听Timer
        /// </summary>
        /// <param name="obj"></param>
        private void ReStartMonitor(object obj)
        {
            if (_lastRecvTime.AddMilliseconds(_maxRecvTime) < DateTime.Now)
            {
                ReStart();
            }
        }
        #endregion
    }
}
